//! Basic usage example for Zig memory management
//! SPDX-License-Identifier: MPL-2.0

const std = @import("std");
const mm = @import("../src/lib.zig");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    std.debug.print("=== Asterinas Zig Memory Management Demo ===\n");

    // 1. 演示基本常量和工具函数
    std.debug.print("\n1. 基本常量:\n");
    std.debug.print("   PAGE_SIZE: {}\n", .{mm.PAGE_SIZE});
    std.debug.print("   NR_LEVELS: {}\n", .{mm.NR_LEVELS});
    std.debug.print("   MAX_USERSPACE_VADDR: 0x{x}\n", .{mm.MAX_USERSPACE_VADDR});

    // 2. 地址对齐演示
    std.debug.print("\n2. 地址对齐:\n");
    const unaligned_addr = 0x1234;
    std.debug.print("   原地址: 0x{x}\n", .{unaligned_addr});
    std.debug.print("   向下对齐: 0x{x}\n", .{mm.alignDown(unaligned_addr, mm.PAGE_SIZE)});
    std.debug.print("   向上对齐: 0x{x}\n", .{mm.alignUp(unaligned_addr, mm.PAGE_SIZE)});
    std.debug.print("   是否页对齐: {}\n", .{mm.isPageAligned(0x1000)});

    // 3. 页大小计算
    std.debug.print("\n3. 页大小计算:\n");
    for (1..5) |level| {
        const size = mm.pageSize(@intCast(level));
        std.debug.print("   Level {} 页大小: {} bytes ({} KB)\n", .{ level, size, size / 1024 });
    }

    // 4. Buddy分配器演示
    std.debug.print("\n4. Buddy分配器演示:\n");
    const memory_start = 0x100000; // 1MB
    const memory_size = 0x100000;  // 1MB
    var buddy = mm.frame.BuddyAllocator.init(memory_start, memory_size);
    const frame_allocator = buddy.frameAllocator();

    // 分配单个帧
    const options = mm.frame.FrameAllocOptions.new().withZeroed(true);
    if (frame_allocator.allocFrame(options, allocator)) |frame| {
        std.debug.print("   成功分配帧: 0x{x} - 0x{x} (大小: {})\n", .{ 
            frame.startPaddr(), frame.endPaddr(), frame.size() 
        });
        
        // 写入数据测试
        const slice = frame.asMutSlice();
        slice[0] = 0xAB;
        slice[1] = 0xCD;
        std.debug.print("   写入测试数据: 0x{x} 0x{x}\n", .{ slice[0], slice[1] });
        
        frame.deinit(allocator);
    } else |err| {
        std.debug.print("   帧分配失败: {}\n", .{err});
    }

    // 分配连续帧段
    if (frame_allocator.allocSegment(4, options, allocator)) |segment| {
        std.debug.print("   成功分配段: {} 帧, 总大小: {} bytes\n", .{ 
            segment.nframes(), segment.totalSize() 
        });
        std.debug.print("   段地址范围: 0x{x} - 0x{x}\n", .{ 
            segment.startPaddr(), segment.endPaddr() 
        });
        
        segment.deinit();
    } else |err| {
        std.debug.print("   段分配失败: {}\n", .{err});
    }

    // 5. 页表演示
    std.debug.print("\n5. 页表演示:\n");
    var page_table = mm.page_table.PageTable.init();
    const walker = mm.page_table.PageTableWalker.init(&page_table);

    const test_vaddr: mm.Vaddr = 0x400000;
    const test_paddr: mm.Paddr = 0x200000;
    const flags = mm.PageFlags{
        .present = true,
        .writable = true,
        .user_accessible = false,
    };

    std.debug.print("   尝试映射: 虚拟地址 0x{x} -> 物理地址 0x{x}\n", .{ test_vaddr, test_paddr });
    
    if (walker.map(test_vaddr, test_paddr, flags, frame_allocator, allocator)) {
        std.debug.print("   映射成功!\n");
        
        if (walker.translate(test_vaddr)) |translated| {
            std.debug.print("   地址转换: 0x{x} -> 0x{x}\n", .{ test_vaddr, translated });
        } else {
            std.debug.print("   地址转换失败\n");
        }
    } else |err| {
        std.debug.print("   映射失败: {}\n", .{err});
    }

    // 6. 虚拟内存空间演示
    std.debug.print("\n6. 虚拟内存空间演示:\n");
    var vm_space = mm.vm_space.VmSpace.init(allocator);
    defer vm_space.deinit();

    const vm_vaddr: mm.Vaddr = 0x500000;
    const vm_paddr: mm.Paddr = 0x300000;
    const vm_size: usize = 4 * mm.PAGE_SIZE;
    const vm_flags = mm.PageFlags{
        .present = true,
        .writable = true,
        .user_accessible = true,
    };

    if (vm_space.map(vm_vaddr, vm_paddr, vm_size, vm_flags, frame_allocator)) {
        std.debug.print("   VMA映射成功: 0x{x} - 0x{x} (大小: {})\n", .{ 
            vm_vaddr, vm_vaddr + vm_size, vm_size 
        });
        
        if (vm_space.findVmArea(vm_vaddr + mm.PAGE_SIZE)) |area| {
            std.debug.print("   找到VMA: 0x{x} - 0x{x}\n", .{ area.start, area.end });
        }
        
        // 取消映射
        if (vm_space.unmap(vm_vaddr, vm_size)) {
            std.debug.print("   VMA取消映射成功\n");
        } else |err| {
            std.debug.print("   VMA取消映射失败: {}\n", .{err});
        }
    } else |err| {
        std.debug.print("   VMA映射失败: {}\n", .{err});
    }

    // 7. DMA演示
    std.debug.print("\n7. DMA演示:\n");
    if (mm.dma.DmaCoherent.init(mm.PAGE_SIZE, frame_allocator, allocator)) |dma_mem| {
        std.debug.print("   DMA内存分配成功: 大小 {}, DMA地址 0x{x}\n", .{ 
            dma_mem.size, dma_mem.daddr() 
        });
        
        // 写入DMA缓冲区
        const dma_slice = dma_mem.asMutSlice();
        dma_slice[0] = 0xDE;
        dma_slice[1] = 0xAD;
        dma_slice[2] = 0xBE;
        dma_slice[3] = 0xEF;
        std.debug.print("   DMA缓冲区写入: 0x{x} 0x{x} 0x{x} 0x{x}\n", .{ 
            dma_slice[0], dma_slice[1], dma_slice[2], dma_slice[3] 
        });
        
        dma_mem.deinit(frame_allocator);
    } else |err| {
        std.debug.print("   DMA内存分配失败: {}\n", .{err});
    }

    std.debug.print("\n=== 演示完成 ===\n");
}

// 错误处理演示
fn demonstrateErrorHandling() void {
    std.debug.print("\n8. 错误处理演示:\n");
    
    // 无效对齐
    const invalid_addr = 0x1001;
    if (!mm.isPageAligned(invalid_addr)) {
        std.debug.print("   检测到无效对齐: 0x{x}\n", .{invalid_addr});
    }
    
    // 地址范围检查
    const user_addr = 0x400000;
    const kernel_addr = 0xffff800000000000;
    
    if (user_addr < mm.MAX_USERSPACE_VADDR) {
        std.debug.print("   用户空间地址: 0x{x} ✓\n", .{user_addr});
    }
    
    if (kernel_addr >= mm.KERNEL_VADDR_START and kernel_addr < mm.KERNEL_VADDR_END) {
        std.debug.print("   内核空间地址: 0x{x} ✓\n", .{kernel_addr});
    }
}